var Utils = {};
(function (){
    var _ua = navigator.userAgent.toLowerCase();
    function check(r){
        return r.test(_ua);
    }
    Utils.isIE = !!window.ActiveXObject;
    Utils.isOldIE = !window.addEventListener;
    Utils.isOpera = !!window.opera;
    Utils.isWebKit = check(/webkit/),
    Utils.isGecko = !Utils.isWebKit && check(/gecko/);
})();

Utils.inherits = function (c, b){
    var f = function (){};
    var s = b.prototype;
    f.prototype = s;
    c.prototype = new f();
    c.constructor = c;
    c.superClass = s
};

Utils.bind = function (fn, thisObj){
    return function (){
        return fn.apply(thisObj, arguments);
    };
};

Utils.assert = function (val, msg){
    if (!val) {
        console.log(msg || '');
        debugger;
    }
};

Utils.nop = new Function();
Utils.abstractMethod = function (){
    throw 'call an abstract method.';
};

Utils.stringRepeat = function (str, count){
    return new Array(count + 1).join(str);
};

Utils.padLeft = function (str, len, ch){
    return new Array(len - str.length + 1).join(ch) + str;
};

Utils.stringEscape = function (str){
    return str.replace(/[\s\S]/g, function (m){
        return '\\u' + Utils.padLeft(m.charCodeAt(0).toString(16), 4, '0');
    });
};

var _map = {'<':'&lt;', '>':'&gt;', '&':'&amp;', ' ':'&nbsp;' };
var _replacer = function (m){ return _map[m]; };
Utils.escapeHTML = function (str){
    return str.replace(/[<>& ]/g, _replacer);
};

Utils.extend = function (c, b){
    var cp = c.prototype;
    var bp = b.prototype;
    for (var k in bp) {
        if (!(k in cp)) {
            cp[k] = bp[k];
        }
    }
};

Utils.camelize = function (str){
    return str.replace(/-./g, function (m){
        return m.charAt(1).toUpperCase();
    });
};

Utils.format = function (tpl, ctx){
    return tpl.replace(/#\{([^}]+)\}/g, function (m, p1){
        return ctx[p1];
    });
};

Utils.keySet = function (array){
    var ret = {};
    var k = array.length;
    while (k --) {
        ret[array[k]] = true;
    }
    return ret;
};

var _lastGuid = -1;
Utils.guid = function (obj){
    return obj._guid || (obj._guid = 'qe:' + ++_lastGuid);
};

Utils.removeItem = function (array, item){
    var k = array.length;
    while (k --) {
        if (array[k] === item) {
            array.splice(k, 1);
            return k;
        }
    }
};

Utils.calcSliceArguments = function (startOffset, endOffset, length){
    if (startOffset == null) {
        startOffset = 0;
    } else if (startOffset < 0) {
        startOffset = length + startOffset;
    }
    if (endOffset == null) {
        endOffset = length;
    } else if (endOffset < 0) {
        endOffset = length + endOffset;
    }
    if (startOffset >= length) {
        startOffset = length;
    }
    if (endOffset < startOffset) {
        endOffset = startOffset;
    }
    return [startOffset, endOffset];
};
if (window.ActiveXObject) {
  XMLHttpRequest = function () {
    try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
      catch (e) {}
    try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
      catch (e) {}
    try { return new ActiveXObject("Microsoft.XMLHTTP"); }
      catch (e) {}
    //Microsoft.XMLHTTP points to Msxml2.XMLHTTP and is redundant
    throw new Error("This browser does not support XMLHttpRequest.");
  };
}

Utils.thinFunction = function (density, fun) {
    if (!density) {
        return fun;
    }
    var timeStamp = 0;
    //density = density > 40 ? 40 : density;
    return function () {
        var callee = arguments.callee;
        if (callee.timer) {
            return;
        }
        var this_ = this;
        var now = +new Date;
        if (now - timeStamp >= density) {
            timeStamp = now;
            return fun.apply(this_, arguments);
        } else {
            var args_ = [].slice.call(arguments, 0);
            var delay = density - now + timeStamp;
            callee.timer = setTimeout(function () {
                callee.timer = null;
                fun.apply(this_, args_);
                timeStamp = +new Date;
            }, delay > 15 ? delay : 15);
        }
    };
};

